// 通用的方法
define([
  "artlib"
], function(template){
  var methods = {};

  /**
   * @Author    李鹏
   * @email     542416615@qq.com
   * @DateTime  2017-08-08
   * @copyright [反序列化，返回json]
   * @param     {[string]}         str ["a=1&b=2"]
   * @return    {[object]}             [{a:1,b:2}]
   */
  methods.unserialize = function(str) {
    if (!str) return {};
    var j = {};

    $.each(str.split("&"), function(i, e) {
      var arr = e.split("=");
      j[arr[0]] = arr[1];
    });

    return j;
  }

  /**
   * @Author    高同檩
   * @copyright [处理序列化值 解决：空格变加号]
   * @param     {[string]}         需要处理的字符串]
   * @return    {[string]}             处理完的字符串]
   */
  methods.resolveSerialize = function(str){
    return str.replace(/\+/g, '%20');
  }

  /**
   * @Author    高同檩
   * @DateTime  2017-09-22
   * @copyright [获取 纯数字 数组中的最大值]
   * @param     {[array]}         array [1,300,20]
   * @return    {[number]}        返回数组中最大值 300
   */
  methods.getArryNumMax = function(arry){
    return Math.max.apply(null, arry);
  }

  /**
   * @Author    高同檩
   * @DateTime  2017-09-22
   * @copyright [获取 纯数字 数组中的最小值]
   * @param     {[array]}         array [1,300,20]
   * @return    {[number]}        返回数组中最小值 1
   */
  methods.getArryNumMin = function(arry){
    return Math.min.apply(null, arry);
  }

  /**
   * @Author    高同檩
   * @DateTime  2018-1-11
   * @copyright [判断对象（花括号对象）是否有属性 {}]
   * @param     {[object]}         object {a:1,b:2}
   * @return    {[boolean]}        true->有属性 false->没有属性
   */
  methods.checkObjecPropty = function(obj){
    var bBoo = false;
    for(var i in obj){
      if(i){
        bBoo = true;
        break;
      }
    }
    return bBoo;
  }

  /**
   * @Author    高同檩
   * @DateTime  2017-09-22
   * @copyright [数字转换千位分隔符]
   * @param     {[number]}         numb [100.00 或者 100]
   * @param     {[boolean]}        noDot true -> 不要小数点 false -> 要小数点
   * @param     {[boolean]}        oneDot true -> 小数点后一位 false -> 小数点后两位
   * @return    {[string]}         返回处理好的千位分隔符
   */
  methods.toThousands = function(numb, noDot, oneDot){
    var num = (numb || 0).toString();
    //判断是否为正数 如果是的话  返回true
    var isNegative=false;
    var rReg = /\./g; //判断是否有 . 符号-正则
    var rReg1 = /\.\d{1}$/; //判断是否是小数点后一位
    var bBoo = rReg.test(num); //判断是否有 . 符号-变量
    var sSympolDian = ""; //小数点后面的数字
    if(bBoo){
      sSympolDian = num.match(/\.\d{1,2}/)[0];
    }else if(oneDot){
      sSympolDian = "";
    }else{
      sSympolDian = ".00";
    }
    num = Math.floor(numb).toString();

    var result = '';
    //判断是否为负数
    if(num<0){
      num = (0-num).toString()
      isNegative=true;
    }
    while (num.length > 3) {
        result = ',' + num.slice(-3) + result;
        num = num.slice(0, num.length - 3);
    }
    if (num) { result = num + result; }

    // 判断是否需要小数点
    if(noDot){
      return result;
    }
    // 返回结果
    result = result + sSympolDian;

    if( rReg1.test(result) && !oneDot ){
      return result + "0";
    }
    // 是负数返回结果
    if(isNegative){
      return "-"+result
    }
    return result;
  }

  /**
   * @Author    高同檩
   * [getViewPortSize 获取浏览器窗口的宽和高]
   * @return {[json]} [宽和高]
   */
  methods.getViewPortSize = function(){
    var winWidth = document.documentElement.clientWidth || document.body.clientWidth;
    var winHeight = document.documentElement.clientHeight || document.body.clientHeight;
    var scrollL = document.documentElement.scrollLeft || document.body.scrollLeft;
    var scrollT = document.documentElement.scrollTop || document.body.scrollTop;
    return {"width": winWidth + scrollL, "height":winHeight + scrollT};
  }

  /**
   * @Author    高同檩
   * [getViewPortSize 获取浏览器类型]
   * @return {[string]} [浏览器类型对应的字符串]
   */
  methods.getExplorer = function(){
    var explorer = window.navigator.userAgent;
    //firefox 
    if (explorer.indexOf("Firefox") >= 0) {
        return "firefox";
    }
    //Chrome
    else if(explorer.indexOf("Chrome") >= 0){
        return "chrome";
    }
    //Opera
    else if(explorer.indexOf("Opera") >= 0){
        return "opera";
    }
    //Safari
    else if(explorer.indexOf("Safari") >= 0){
        return "safari";
    }
    // ie
    else{
        return "ie";
    }
  }

  /**
   * @Author    高同檩
   * @DateTime  2017-09-26
   * @copyright [arttemplate渲染-调用的是 template的基础方法（渲染基于 script 模板的id）]
   * @param     {[listEle]}     渲染元素 需要传jquery对象
   * @param     {[tplId]}       模板id
   * @param     {[data]}        渲染数据源
   * @param     {[isAppend]}    是否是向后追加元素 true -> 向后追加 false(默认值) -> 直接覆盖
   * @return    {[null]}        null
   */
  methods.artRender = function(listEle, tplId, data, isAppend){
    var sTpl = template(tplId, data);
    if(isAppend){
      listEle.append(sTpl);
    }else{
      listEle.html(sTpl);  
    }
  }

  /**
   * @Author    高同檩
   * @DateTime  2017-09-28
   * @copyright [arttemplate渲染-调用的是 template的 render 方法(渲染基于字符串)]
   * @param     {[listEle]}     渲染元素 需要传jquery对象
   * @param     {[tpl]}         模板内容，及模板字符串
   * @param     {[data]}        渲染数据源
   * @param     {[isAppend]}    是否是向后追加元素 true -> 向后追加 false(默认值) -> 直接覆盖
   * @return    {[null]}        null
   */
  methods.artRenderString = function(listEle, tpl, data, isAppend){
    var sTpl = template.render(tpl, data);
    if(isAppend){
      listEle.append(sTpl);
    }else{
      listEle.html(sTpl);  
    }
  }

  /**
   * @Author    高同檩
   * @DateTime  2018-01-10
   * @copyright [渲染数据为空的方法]
   * @param     {[obj]}     渲染对象元素 需要传jquery对象
   * @param     {[opt]}         配置参数
   * @return    {[null]}        null
   */
  methods.renderBlankContent = function(obj, opt){
    var sTpl = "";
    var defaults = {
      iTop: "30px",//距离顶部的距离
      iType: ""
    }
    $.extend(true, defaults, opt);
    switch(defaults.iType){
      case 1:
        break;
      default:
        sTpl = '<div class="content_blank" style="margin-top:'+ defaults.iTop +';">' +
                  '<div class="pic common"></div>' +
                  '<p class="con">暂无相关数据</p>' +
                '</div>';

    }
    obj.html(sTpl);
  }

  /**
   * @Author    高同檩
   * @DateTime  2017-09-29
   * @copyright [获取url search部分 指定名称的属性值]
   * @param     {[string]} name    要获取的属性的属性名
   * @return    {[string]}         指定名称的属性值
   */
  methods.getUrlParam = function(name){
    var reg     = new RegExp('(^|&)' + name + '=([^&]*)(&|$)');
    var result  = window.location.search.substr(1).match(reg);
    return result ? decodeURIComponent(result[2]) : null;
  }

  /**
   * @Author    高同檩
   * @DateTime  2017-12-1
   * @copyright [清除select框option选项（保留第一个）]
   * @param     {[object jquery]} 要清除的select jquery对象
   * @return    {[null]}
   */
  methods.clearSelectOptionOne = function(jqObj){
    var aOption = jqObj.find("option");
    $( aOption.splice(1, aOption.length + 1) ).remove();
  }

  /**
  * [check_number 校验文本域输入字数]
  * @param  {[object]} area   [文本域对象(选择器)]
  * @param  {[object]} curr   [输入字数对象(选择器)]
  * @param  {[object]} totalNub   [总字数dom对象(选择器)]
  * @param  {[object]} total  [总字数]
  */
  methods.check_number=function(area,curr,totalNub,total){
    var areaObj = $(area);
    var iStr = areaObj.val() ? areaObj.val().length: 0; //获取文本域的值
    $(totalNub).html(total);
    $(curr).html(iStr);
    areaObj.on('input propertychange',function(){
        var curr_length = $(area).val().length;
        if(curr_length > total){
           $(area).val($(area).val().substring(0,total));
        }else{
            $(curr).html(curr_length);
        }
    })
    areaObj.change(function(){
      $(curr).html( $(this).val().length );
    });
  }

  /**
   * @Author    高同檩
   * @DateTime  2018-1-5
   * @copyright [获取客户端的年月日]
   * @return    {[object]}
   */
  methods.getClientTime = function(){
    var oDate = new Date();
    var sYear = oDate.getFullYear();
    var sMonth = oDate.getMonth() + 1;
    var sDay = oDate.getDate();
    sMonth = sMonth >= 10 ? sMonth : "0" + sMonth;
    sDay = sDay >= 10 ? sDay : "0" + sDay;
    return {year: sYear, month: sMonth, day: sDay};
  }

  /**
   * @Author    高同檩
   * @DateTime  2018-1-5
   * @copyright [时间验证 格式 年月日 2018-01-05]
   * @param     {[object]}
   *  参数一 folder 开始结束时间包裹层
   *  参数二 start  开始时间
   *  参数三 end    结束时间
   * @return    {[null]}
   */
  methods.verifyTimeCorrect = function(opt){
    var defaults = {
      folder: "[data-role='verify_time']",
      start: "[data-role='verfiy_time_start']",
      end: "[data-role='verfiy_time_end']"
    }
    var config = $.extend({}, defaults, opt);
    var aFolder = $(config.folder);
    aFolder.each(function(){
      var oStart = $(this).find("input" + config.start);
      var oEnd = $(this).find("input" + config.end);
      var sStart = oStart.val();
      var sEnd = oEnd.val();
      if( sStart && sEnd ){
        var iStart = new Date( sStart ).getTime();
        var iEnd = new Date( sEnd ).getTime();
        if(iStart > iEnd){
          oStart.val( sEnd );
          oEnd.val( sStart );
        }
      }
    });
  }

  /**
   * @Author    高同檩
   * @DateTime  2018-1-8
   * @copyright [设置按钮的状态 文字、颜色、禁用]
   * @param     {[ele]} 发生事件的对象(jquery对象)
   * @param     {[opt]} 配置对象
   * @return    {[null]}
   */
  methods.setBtnStatus = function(ele ,opt){
    var defaults = {
      txt: "",//初始化的文字(需要传进来)
      disable_class: "disable",
      status: true//true->恢复正常 false->禁用
    }
    var config = $.extend(true, defaults, opt);
    if(config.status){
      ele.removeClass(config.disable_class).html(config.txt);
    }else{
      ele.addClass(config.disable_class).html("保存中...");
    }
  }

  /**
   * @Author    高同檩
   * @DateTime  2018-1-8
   * @copyright [检测是否有特定的class名称]
   * @param     {[ele]} 发生事件的对象(jquery对象)
   * @param     {[clsName]} 要检测的class名称
   * @return    {[boolean]} true->有 false->没有
   */
  methods.checkBtnClass = function(ele, clsName){
    var sClsName = clsName || "disable";
    return ele.hasClass(sClsName);
  }

  /**
   * [inputFixNumFun $.parseInputNumber方法&parseInputNumber方法 限制输入数字公用的方法]
   * @param  {[object]} objThis   [发生事件的输入框元素]
   * @param  {[object]} objConfig [限制数字方法的配置]
   * @param  {[function]} call      [回调方法（目前有blur和change事件如需新增事件请自行添加）]
   * @return {[null]}           [null]
   */
  methods.inputFixNumFun = function(objThis, objConfig, call){
    var rRegNum = /[^((0-9)|\.)]+/g;
    var sStr = objThis.val();
    sStr = sStr.replace(rRegNum, "");
    var iStr = parseFloat(sStr);
    if(sStr != "" && isNaN(iStr)){
      objThis.val("0.00");
    }else if(sStr == ""){
      objThis.val("");
    }else{
      var iNum = iStr.toFixed(objConfig.fixNum) - 0;
      if(objConfig.min !== -1){
        iNum = iNum < objConfig.min ? objConfig.min : iNum ;
      }
      if(objConfig.max !== -1){
        iNum = iNum > objConfig.max ? objConfig.max : iNum ;
      }
      objThis.val(iNum.toFixed(objConfig.fixNum));
    }
    // 设置回调函数
    call && call(objThis, objThis.val());
  }

  /**
   * [$.parseInputNumber input文本框输入限制]
   * @param  {[object]} opt [配置对象]
   *     fixNum  {number} [数字保留位数]
   *     eventBeforeFun {function} [事件触发前 回调 用于修改参数]
   *     blurFun {function} [输入框赋值完后的 失去焦点事件 回调]
   *     changeFun {function} [输入框赋值完后的 change事件 回调]
   * @return {[null]}     [null]
   */
  $.fn.parseInputNumber = function(opt){
    var opt = opt || {};
    var defaults = {
      eventBeforeFun: "",
      blurFun: "",
      changeFun: "",
      fixNum: 2,
      min: -1,
      max: -1
    }
    var config = $.extend({} ,defaults, opt);
    
    return this.each(function(i, val){
      var _this = $(val);
       
      _this.blur(function() {
        config.eventBeforeFun &&config.eventBeforeFun(config, _this );
        methods.inputFixNumFun(_this, config, config.blurFun);
      });

      _this.change(function() {
        config.eventBeforeFun &&config.eventBeforeFun(config, _this );
        methods.inputFixNumFun(_this, config, config.changeFun);
      });
    })
  }

  /**
   * [parseInputNumber input文本框输入正数限制]
   * @param  {[object]} opt [配置对象]
   *     parent  {string} [事件委托的父级对象默认为 document]
   *     inpEle  {string} [发生事件的对象]
   *     fixNum  {number} [数字保留位数]
   *     eventBeforeFun {function} [事件触发前 回调 用于修改参数]
   *     blurFun {function} [输入框赋值完后的 失去焦点事件 回调]
   *     changeFun {function} [输入框赋值完后的 change事件 回调]
   * @return {[null]}     [null]
   */
  methods.parseInputNumber = function(opt){
    var opt = opt || {};
    var defaults = {
      parent: "",
      inpEle: "",
      eventBeforeFun: "",
      blurFun: "",
      changeFun: "",
      fixNum: 2,
      min: -1,
      max: -1
    }
    // var rRegNum = /[^((0-9)|\.)]+/g;
    var config = $.extend({} ,defaults, opt);
    var oParent = config.parent ? config.parent : document;
    $(oParent).on("blur", config.inpEle, function(ev){
      var oEv = ev || window.event;
      oEv.stopPropagation();
      var _this = $(this);
      config.eventBeforeFun &&config.eventBeforeFun(config, _this );
      methods.inputFixNumFun(_this, config, config.blurFun);
    })

    $(oParent).on("change", config.inpEle, function(ev){
      var oEv = ev || window.event;
      oEv.stopPropagation();
      var _this = $(this);
      config.eventBeforeFun &&config.eventBeforeFun(config, _this );
      methods.inputFixNumFun(_this, config, config.changeFun);
    })
  }

  /**
   * [verifyArrayValNotSame 校验数组不能有相同的值 eg:[1,2,3,2] 目前是有相同的就终止验证 ]
   * @param  {[object]} opt [配置对象]
   * @return {[boolean]}     [true -> 没有相同的值 false -> 有相同的值]
   */
  methods.verifyArrayValNotSame = function(opt){
    var opt = opt || {};
    var defaults = {
      array: "",//需要验证的数组
    }
    var config = $.extend({} ,defaults, opt);
    var bBoo = true;//最终返回值
    var bBooIn = true;//内部循环判断
    if(config.array.length == 1){
      return true;
    }
    $(config.array).each(function (i, val) {
      if(!bBooIn){
        return false;
      }
      var aArr = $(config.array).slice(i+1, config.array.length);
      aArr.each(function (j, value) {
        if(val != value){
          bBoo = false;
          bBooIn = false;
          return false;
        }
      });
    });
    return bBoo;
  }

  /**
   * [deleteArrayEle 删除数组中的元素(源数组不会变) ]
   * @param  {[arry]} opt [源数组]
   * @param  {[idx]} opt [删除的索引]
   * @return {[array]}     [新的数组]
   */
  methods.deleteArrayEle = function(arry, idx){
    var aBefore = arry.slice(0, idx);
    var aAfter = arry.slice(idx+1, arry.length);
    return aBefore.concat(aAfter);
  }

  // 将方法暴露出去
  return methods;
});